package com.sf.datastructure.imageUtil;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import javax.imageio.ImageIO;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sf.module.common.constants.SysConstants;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 图片处理工具类
 */
public class ImageUtils {
	
	private ImageUtils() {}

    /**
     * logger
     */
	private static final Logger logger = LoggerFactory.getLogger(ImageUtils.class);

	/**
     * 压缩图片
     * @param src 源图片路径
     * @param des 新图片路径
     * @param maxWidth 限定宽度
     * @return
     */
    public static boolean compressPic(String src, String des, int maxWidth) {
        try {
            // 获得源文件
            File file = new File(src);
            if (!file.exists()) {
                return false;
            }
            Image img = ImageIO.read(file);
            int width = img.getWidth(null);
            int height = img.getHeight(null);
            // 判断图片格式是否正确
            if (width == -1) {
                return false;
            } else {
                int newWidth = width;
                int newHeight = height;
                /**
                 * 图片压缩，判断原图宽度是否超过限定宽度，
                 * 	如果超过，宽度设置为限定宽度，长度设置为原图片长度*（限定宽度/原图片宽度）
                 * 	如果不超过，宽度、长度值不变
                 */
                if (width > maxWidth) {
                    newWidth = maxWidth;
                    newHeight = (int) (maxWidth * ((double)height / (double)width));
                }
                /**生成图片*/
                saveImage(img, des, newWidth, newHeight);
            }
        } catch (Exception ex) {
            logger.error("img compress exception 图片", ex);
            return false;
        }
        return true;
    }
	
	/**
	 * 压缩图片
	 * @param src 源图片路径
	 * @param des 新图片路径
	 * @param width 限定宽度
	 * @param height 限定高度
	 * @return
	 */
	public static boolean compressPic(String src, String des, int width, int height) {
		try {
			// 获得源文件
			File file = new File(src);
			if (!file.exists()) {
				return false;
			}
			Image img = ImageIO.read(file);
			// 判断图片格式是否正确
			if (width == -1) {
				return false;
			} else {
				/**生成图片*/
				saveImage(img, des, width, height);
			}
		} catch (Exception ex) {
			logger.error("img compress exception", ex);
			return false;
		}
		return true;
	}
	
	/**
	 * 生成大小缩略图
	 * @param src 源图片路径
	 * @param largeDest 大图图片路径
	 * @param largeWidth 大图最大宽度
	 * @param largeHeight 大图最大高度
	 * @param smallDest 小图图片路径
	 * @param smallWidth 小图最大宽度
	 * @param smallHeight 小图最大高度
	 * @return
	 */
	public static boolean smallPic(String src, String largeDest, int largeWidth, int largeHeight, 
			String smallDest, int smallWidth, int smallHeight) {
		try {
			// 获得源文件
			File file = new File(src);
			if (!file.exists()) {
				return false;
			}
			Image img = ImageIO.read(file);
			int width = img.getWidth(null);
			int height = img.getHeight(null);
			// 判断图片格式是否正确
			if (width == -1) {
				return false;
			} else {
				int newWidth = width;
				int newHeight = height;
				int newSmallWidth ;
				int newSmallHeight;
				/**
				 * 判断原图宽度是否超过最大宽度，原图高度是否超过最大高度
				 * 	如果原图宽度超过最大宽度，并且原图高度也超过最大高度，比较原图宽高比例与最大宽高比例，
				 * 		如果原图宽高比例大于最大宽高比例，取最大宽度为新宽度，等比例缩小高度
				 * 		否则，取最大高度为新高度，等比例缩小宽度
				 * 	如果原图宽度超过最大宽度，原图高度小于等于最大高度，取最大宽度为新宽度，等比例缩小高度
				 * 	如果原图宽度小于等于最大宽度，原图高度大于最大高度，取最大高度为新高度，等比例缩小宽度
				 * 	否则，长宽不变
				 */
				if (width > largeWidth && height > largeHeight) {
					if (((double)width/(double)height) > ((double)largeWidth/(double)largeHeight)) {
						newWidth = largeWidth;
						newHeight = (int) (largeWidth * ((double)height / (double)width));
					} else {
						newWidth = (int) (largeHeight * ((double)width / (double)height));
						newHeight = largeHeight;
					}
				}
				/**生成预览图片*/
				saveImage(img, largeDest, newWidth, newHeight);
				
				/**生成缩略图片*/
				if (((double)width/(double)height) > ((double)smallWidth/(double)smallHeight)) {
					newSmallWidth = smallWidth;
					newSmallHeight = (int) (smallWidth * ((double)height / (double)width));
				} else {
					newSmallWidth = (int) (smallHeight * ((double)width / (double)height));
					newSmallHeight = smallHeight;
				}
				saveImage(img, smallDest, newSmallWidth, newSmallHeight);
			}
		} catch (Exception ex) {
			logger.error("img compress exception", ex);
			return false;
		}
		return true;
	}
	
	/**
	 * 生成图片
	 * @param img 源图片
	 * @param filePath 图片存放路径
	 * @param width 图片宽度
	 * @param height 图片高度
	 * @throws Exception
	 */
	@SuppressWarnings("restriction")
	private static void saveImage(Image img, String filePath, int width, int height) {
		
		try {
			BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			
			/**
			 * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢
			 */
			tag.getGraphics().drawImage(img.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
			FileOutputStream out = new FileOutputStream(filePath);
			
			/** JPEGImageEncoder可适用于其他图片类型的转换 */
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(tag);
			out.close();
		}catch(Exception e) {
			logger.error(e.getMessage(),e);
		}
		
	}
	
	/**
	 * 从给定的内容中查找第一条图片，如果有的话
	 * @param content
	 * @author weiliang.mao
	 * @return
	 */
	public static String findFirstImageUrlFromContent(String content){
		if(content == null){
			return null;
		}
		Document doc = Jsoup.parse(content);
		List<Element> nodes = doc.body().getElementsByTag("img");
		if(!nodes.isEmpty()){
			String imageUrl = nodes.get(0).attr("src");
			if(imageUrl != null && imageUrl.startsWith(SysConstants.getAttachmentViewPath())){
				imageUrl = imageUrl.substring(SysConstants.getAttachmentViewPath().length());
			}
			return imageUrl;
		}
		return null;
	}
/*
	// compressPic(大图片路径,生成小图片路径,大图片文件名,生成小图片文名,生成小图片宽度,生成小图片高度,是否等比缩放(默认为true))
	public static void main(String[] arg) {
		// 448 280
		//compressPic("D:/temp/img/test.jpg", "D:/temp/img/test1.jpg", 400);
//		compressPic("D:/temp/img/cmtypic.gif", "D:/temp/img/cmtypic1.gif", 300);
		smallPic("D:/temp/img/suolue.jpg", "D:/temp/img/suolue_large.jpg", 500, 400, "D:/temp/img/suolue_small.jpg", 50, 40);
	}*/
	
	 public static BufferedImage rotateImage(Image src, int angel) {  
	        int src_width = src.getWidth(null);  
	        int src_height = src.getHeight(null);  
	        // calculate the new image size  
	        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(  
	                src_width, src_height)), angel);  
	  
	        BufferedImage res = new BufferedImage(rect_des.width, rect_des.height,  
	                BufferedImage.TYPE_INT_RGB);  
	        Graphics2D g2 = res.createGraphics();  
	        // transform  
	        g2.translate((rect_des.width - src_width) / 2,  
	                (rect_des.height - src_height) / 2);  
	        g2.rotate(Math.toRadians(angel), (double)src_width / 2, (double)src_height / 2);  
	  
	        g2.drawImage(src, null, null);  
	        return res;  
	    }  
	  
	    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {  
	        // if angel is greater than 90 degree, we need to do some conversion  
	        if (angel >= 90) {  
	            if(angel / 90 % 2 == 1){  
	                int temp = src.height;  
	                src.height = src.width;  
	                src.width = temp;  
	            }  
	            angel = angel % 90;  
	        }  
	  
	        double r = Math.sqrt(src.height * (double)src.height + src.width * src.width) / 2;  
	        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;  
	        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;  
	        double angel_dalta_width = Math.atan((double) src.height / src.width);  
	        double angel_dalta_height = Math.atan((double) src.width / src.height);  
	  
	        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha  
	                - angel_dalta_width));  
	        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha  
	                - angel_dalta_height));  
	        int des_width = src.width + len_dalta_width * 2;  
	        int des_height = src.height + len_dalta_height * 2;  
	        return new Rectangle(new Dimension(des_width, des_height));
	    }  
	
	public static void main(String[] args) throws IOException {
		File origThumbnail = new File("D:/app/basefs/KMS-MSERVER/culture/video/001/464/972/674/206/2b51deb3-ddc2-480a-b322-65a9b8c46a5e.mp4_orig.thumbnail");
		BufferedImage bufferedimage =ImageIO.read(origThumbnail );
		BufferedImage rotateImage = ImageUtils.rotateImage(bufferedimage , 100);
		ImageIO.write(rotateImage, "JPEG", new File("D:/app/basefs/KMS-MSERVER/culture/video/001/464/972/674/206/xx1.jpg"));
	}
}
